#include "NoisegenUI.hpp"

static const TCHAR APPLICATION_NAME[] = TEXT("noisegen");

NoisegenUI::NoisegenUI(HINSTANCE instance)
{
  m_icon32 = reinterpret_cast<HICON>(LoadImage(instance, MAKEINTRESOURCE(IDI_ON), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR));
  m_icon16On = reinterpret_cast<HICON>(LoadImage(instance, MAKEINTRESOURCE(IDI_ON), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR));
  m_icon16Off = reinterpret_cast<HICON>(LoadImage(instance, MAKEINTRESOURCE(IDI_OFF), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR));
  m_instance = instance;

  if (!RegisterMainClass())
    throw new exception("Couldn't register the main class.");

  if (CreateMainWindow(m_instance) == NULL)
    throw new exception("Couldn't create the main window.");
}

bool NoisegenUI::RegisterMainClass()
{
  WNDCLASSEX wce;

  ZeroMemory(&wce, sizeof(wce));
  wce.cbSize        = sizeof(wce);
  wce.lpfnWndProc   = &WndProc;
  wce.hInstance     = m_instance;
  wce.hIcon         = m_icon32;
  wce.hIconSm       = m_icon16Off;
  wce.lpszClassName = APPLICATION_NAME;

  return (RegisterClassEx(&wce) != 0);
}

HWND NoisegenUI::CreateMainWindow(HINSTANCE instance)
{
  return CreateWindow(APPLICATION_NAME, APPLICATION_NAME, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, instance, this);
}

int NoisegenUI::Run()
{
  MSG msg;
  while (GetMessage(&msg, NULL, 0, 0) > 0)
  {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }
  return static_cast<int>(msg.wParam);
}

LRESULT CALLBACK NoisegenUI::WndProc(HWND window, unsigned int message, WPARAM wParam, LPARAM lParam)
{
  static NoisePlayer    noisePlayer;
  static SystemTrayIcon trayIcon(window, ICON_ID);
  static bool           playing = false;
  static NoisegenUI*    thisUI;

  switch (message)
  {
  case WM_CREATE:
    thisUI = reinterpret_cast<NoisegenUI*>(reinterpret_cast<CREATESTRUCT*>(lParam)->lpCreateParams);
    trayIcon.Create(thisUI->m_icon16Off, APPLICATION_NAME);
    noisePlayer.SetAmplitude(MAXSHORT);
    break;

  case WM_SYSTEMTRAY:
    switch (LOWORD(lParam))
    {
    case WM_LBUTTONDBLCLK:
      if (playing ? noisePlayer.StopPlaying() : noisePlayer.StartPlaying())
        playing = !playing;

      trayIcon.ChangeIcon(playing ? thisUI->m_icon16On : thisUI->m_icon16Off);
      break;

    case WM_RBUTTONDOWN:
      {
        HMENU menu = CreatePopupMenu();
        if (menu != NULL)
        {
          AppendMenu(menu, MF_STRING | MF_DISABLED | MF_GRAYED, 0, TEXT("created by Brandon Hsiao"));
          AppendMenu(menu, MF_STRING | MF_SEPARATOR, 0, NULL);
          AppendMenu(menu, MF_STRING, IDM_ABOUT, TEXT("About"));
          AppendMenu(menu, MF_STRING, IDM_SETTINGS, TEXT("Settings"));
          AppendMenu(menu, MF_STRING | MF_SEPARATOR, 0, NULL);
          AppendMenu(menu, MF_STRING, IDM_EXIT, TEXT("Exit"));

          POINT point;
          if (GetCursorPos(&point))
            if (SetForegroundWindow(window))
              TrackPopupMenu(menu, TPM_BOTTOMALIGN | TPM_RIGHTALIGN, point.x, point.y, 0, window, NULL);
          
          DestroyMenu(menu);
        }
      }
    }
    break;

  case WM_COMMAND:
    switch (LOWORD(wParam))
    {
    case IDM_ABOUT:
      MessageBox(window, TEXT("noisegen was created as a small & quick replacement for SimplyNoise. This program is free.\n\nTo start/stop the noise, simply double-click the icon. The noise will play at the volume your computer is currently set to."), APPLICATION_NAME, MB_OK | MB_ICONINFORMATION);
      break;

    case IDM_SETTINGS:
      MessageBox(window, TEXT("noisegen doesn't have any settings yet but might in future versions."), APPLICATION_NAME, MB_OK | MB_ICONINFORMATION);
      break;

    case IDM_EXIT:
      CallWindowProcA(WndProc, window, WM_CLOSE, 0, 0);
      break;
    }
    break;

  case WM_CLOSE:
    trayIcon.Destroy();
    DestroyWindow(window);
    break;

  case WM_DESTROY:
    PostQuitMessage(EXIT_SUCCESS);
    break;
  }
  return DefWindowProc(window, message, wParam, lParam);
}